{
  LW Polygon -- Layout Interactive Tools

    This header defines the polygon handler.  A polygon type is defined by
  one of these structures.  The struct contains its four-character type
  code, some flags, and a private data pointer to be used by the polygon
  type implementation, plus a set of callback functions used to implement
  the generic behaviors of this type of polygon.

  Based on lwpolygon.h which is:
  Copyright 2004, NewTek, Inc.
}

{
  Copyright 2012, Jameel Halabi

  This unit is part of the BlaiseWave wrapper,
  which is licensed under the BSD 2-Clause license (see licenses/license.txt).
}

unit LW_Polygon;

{$mode objfpc}{$H+}

interface

uses
  LW_Types   ,
  LW_Tool    ,
  LW_Meshes  ,
  LW_Handler ,
  LW_Render  ;

const
  { Meshes
    Polygons are converted to a surface mesh using the 'genMesh' function.  The
    optional 'tstMesh' function can also be provided to allow the client to
    test whether a mesh will be generated for the given polygon.  If there is
    no mesh then the client can save a lot of setup time.  The 'genMesh'
    function returns its data in a struct with the following fields. }
  LWPMI_NORMALS = 1 ;
  LWPMI_TEXTURE = 2 ;

  LWGPTF_SURFACE = 1 ;
  LWGPTF_FLAT    = 2 ;
  LWGPTF_LINEAR  = 4 ;
  LWGPTF_SUBD    = 8 ;

  { The change flag contains a set of bits defining the types of changes that
    can occur to layer data.  A geometric change is a change to the number of
    points and polygons or their interconnections.  A positional change is a
    change in the location of points. A surface change is a change to the
    surface attributes of polygons. A VMap change is a change to the content
    of any VMaps. }
  SYNC_GEOMETRY = 1  ;
  SYNC_POSITION = 2  ;
  SYNC_SURFACE  = 4  ;
  SYNC_VMAP     = 8  ;
  SYNC_TAGS     = 16 ;

  LWPOLYGON_HCLASS   = 'PolygonHandler' ;
  LWPOLYGON_VERSION  = 5 ;


type

  PLWPolyMeshInfo = ^TLWGPolMeshInfo ;
  TLWGPolMeshInfo = record
    {  This flag will be set for you to indicate which additional mesh data
       is being requested.
       When set to LWPMI_NORMALS, please compute and supply a 'norm' array.
       When set to LWPMI_TEXTURE, please compute and supply
       texture data via 'itex' and 'wtex'.
       You should always specify the 'vrts' and 'pols' arrays. }
    Flag	: Integer ;

    { The type is 3 or 4, where 3 indicates that this is a triangle mesh
      and 4 indicates that it is a quad mesh.  A type of zero indicates no mesh. }
    Type_	: Integer ;

    { Number of vertices in the polygon's mesh }
    NVrt	: Integer ;

    { Number of surface polygons this specific polygon instance has generated }
    NPol        : Integer ;

    {  Texture information is organized into a set of tuples;
      one tuple associated with each vertex in the mesh of polygons.
      Each point in the mesh is associated with an n-tuple of polygon vertices
      and weights, with the tuple order specified by 'ntex.'
      NOTE: Still need to understand this one. }
    NTex	: Integer ;

    {  The polygons in the mesh are specified by indices into the
     vertex array 'vrts'.  There are 'npol' polygons and the indicies
     are grouped into triples or quads based on the mesh type. }
    Pols	: PInteger ; // const

    { The vertices of the polygon mesh are given by an array of floats
      organized into 'nvrt' triples. }
    Vrts	: PSingle  ; // const

    { The normals of the polygon mesh are given by an array of floats
      organized into 'nvrt' triples.
      NOTE: These probably should be normalized direction vectors (x,y,z)
      This only is needed when 'flag' is set the LWPMI_NORMALS. }
    Norm	: PSingle  ; // const

    { The 'itex' array holds the indices of the polygon vertices used in a texture. }
    ITex	: PInteger ; // const

    { The 'wtex' array holds the weight of each texture-polygon vertex. }
    WTex	: PSingle  ; // const
  end;

  // Access structure much like the Meshinfo structure described elsewhere
  PLWPolygonTypeAccess = ^TLWPolygonTypeAccess ;
  TLWPolygonTypeAccess = record
    Priv          : Pointer ;
    PntVLookup    : function
                    (       PolAccess : PLWPolygonTypeAccess ;
                            VMAPType  : PLWID                ;
                      const VMAPName  : PChar                ) : Pointer ;
    PntVIDGet     : function
                    (       PolAccess : PLWPolygonTypeAccess ;
                            Point     : PLWPnt               ;
                            Vector    : PSingle              ;
                            VMAPID    : Pointer              ) : Integer ;
    PntOtherPos   : procedure
                    (       PolAccess : PLWPolygonTypeAccess ;
                            Point     : PLWPnt               ;
                            Pos       : TLWFVector           ) ;
    ScanPolys     : function
                    (       PolAccess : PLWPolygonTypeAccess ;
                            ScanFunc  : TLWPolScanFunc       ;
                            UserData  : Pointer              ) : Integer ;
    { "Polygon" here refers to a number of different kinds of geometric atoms,
      including things like curves and bones.
      The polygon type codes are an extensible set of four-character identifiers.
      The header file lwmeshes.h defines the most common ones:

        LWPOLTYPE_FACE - face
        LWPOLTYPE_CURV - higher order curve
        LWPOLTYPE_PTCH - subdivision control cage polygon
        LWPOLTYPE_MBAL - metaball
        LWPOLTYPE_BONE - bone

      Do not assume that these are the only polygon types in existence.
      Restricting an operation to work only on particular polygon types
      is discouraged. For example, if an operation can only be applied
      to polygons that are renderable, do not filter out all polygons
      whose type is face. Instead, use the polTypeFlags() meshinfo
      function to check for the LWGPTF_SURFACE flag. }
    PolType       : function
                    (       PolAccess : PLWPolygonTypeAccess ;
                            Polygon   : PLWPol               ) : PLWID   ;
    PolSize       : function
                    (       PolAccess : PLWPolygonTypeAccess ;
                            Polygon   : PLWPol               ) : Integer ;
    PolVertex     : function
                    (       PolAccess : PLWPolygonTypeAccess ;
                            Polygon   : PLWPol               ;
                            VertIndex : Integer              ) : PLWPnt  ;
    PolTag        : function
                    (       PolAccess : PLWPolygonTypeAccess ;
                            Polygon   : PLWPol               ;
                            TagID     : PLWID                ) : PChar  ; // const
  end;

  { Essentially a copy of the st_LWWireDrawAccess structure in lwtool.h,
    with the addition of the "edge_idx" parameter to the "lineTo" function. }
  PLWPtypeWireDrawAccess = ^TLWPtypeWireDrawAccess ;
  TLWPtypeWireDrawAccess = record
    // Pointer to private data used by the implementation.
    Data   : Pointer;

    // Move cursor to a specific position without drawing.
    // returns 0 if the linemode is not supported
    MoveTo : procedure
             (      Data          : Pointer   ;
                    Pos           : TLWFVector;
                    LineMode      : Integer   ) ;

    // Draw a line from the current cursor position to a given position.
    //
    // @param EdgeIndex In case a polygon is drawn this parameter should specify
    //                  the edge index starting from the edge between
    //                  the vertices (n-1, 0) as edge with index 0.
    LineTo : procedure
             (      Data          : Pointer   ;
                    Pos           : TLWFVector;
                    CoordSystem   : Integer   ;
                    EdgeIndex     : Integer   ) ;

    // Draw a spline from the current cursor position.
    Spline : procedure
             (      Data          : Pointer   ;
                    CP0, CP1, CP2 : TLWFVector;
                    CoordSystem   : Integer   ) ;

    // Draw a circle with the given radius around the current point.
    Circle : procedure
             (      Data          : Pointer   ;
                    Radius        : Double    ;
                    CoordSystem   : Integer   ) ;

    // 0, 1, or 2 for orthogonal views, -1 for a perspective view.
    Axis   : Integer;

    // Draw the specified text at the current position
    Text   : procedure
             (      Data          : Pointer   ;
              const TextLine      : PChar     ;
                    Justify       : Integer   ) ;

    PXScale : Double;
  end;

  { Polygon Type
    This polygon type structure is used as the interface between
    the host and your custom polygon definition.                }
  PLWPolyType = ^TLWPolyType ;
  TLWPolyType = record
    { Four Character Type Code. Use LWID_ in lwtypes.h to create.
      There are several 'built-in' types that can not be used for
      custom polygon types.                                       }
    Type_     : PLWID ;
    { This contains bits that determine what kind of polygon this is.
      If the LWGPTF_SURFACE bit is set, then this type of polygon renders
      as a surface and a mesh should be generated.
      If LWGPTF_FLAT   is set, then the surface is intended to be flat.
      If LWGPTF_LINEAR is set, then the polygon type is a linear curve and the
      order of the points determines absolute direction rather than sidedness. }
    Flags     : Integer ;
    { This is called when an instance of your custom polygon needs to be drawn
      in a view port using basic drawing functions.
      The specific polygon to displayed and the means to obtain to the vertexes
      are given along with the means to draw into the view port.
      NOTES: The specifics about the view port may be needed as well.
      More advanced drawing capabilities like textured quads may be added later. }
    Display   : procedure
                (        Instance    : Pointer                ;
                         PolygonID   : PLWPol                 ;
                   const Access      : PLWPtypeWireDrawAccess ;
                         PolTypeInfo : PLWPolygonTypeAccess   ) ;
    { This is called when an instance of your custom polygon needs to generate
      a standard surface mesh which can consist of vertices, triangles or quads,
      normal vectors, and texture weightings.
      The polygon specifies the custom polygon for which a mesh is needed.
      The vertex_instance allows access to the vertices for the existing
      custom polygon.
      The mesh is a structure that you fill in.
      (see definition in this header above.) }
    GenMesh   : procedure
                (        Instance    : Pointer                ;
                         PolygonID   : PLWPol                 ;
                         MeshInfo    : PLWPolyMeshInfo        ;
                         PolTypeInfo : PLWPolygonTypeAccess   ) ;
    { This is called to test if the given custom polygon instance is to be used.
      Return 0 if not, 1 if yes. }
    TstMesh   : function
                (        Instance    : Pointer                ;
                         PolygonID   : PLWPol                 ;
                         PolTypeInfo : PLWPolygonTypeAccess   ) : Integer ;

    // Private Data, GCore Usage.
    Index      : Integer  ;
    Data       : Pointer  ;

    { The 'startup' and 'shutdown' functions are used by the host when
     adding and removing the polygon type.
     The private data should be managed by these functions. }
    Startup    : procedure
                 (        PolType     : PLWPolyType            ) ;
    // Called Once When Plugin Unloaded.
    Shutdown   : procedure
                 (        PolType     : PLWPolyType            ) ;
    { This is called when an instance of your custom polygon type is being created.
     Any necessary memory allocation and setup should be done here.

     A polygon type gets a chance to allocate some data for every one of the
     vertex instances in the system.  The 'alloc' function is called with the
     vertex instance and the polygon type and should return any allocated data
     necessary to implement the polygon behaviors for that instance.  The 'free'
     function is obviously called to destroy that data.  The type implementation
     can access the data by indexing into an array stored in each vertex
     instance, at the 'index' offset. }
    Alloc      : function
                 (        PolTypeInfo : PLWPolygonTypeAccess   ) : Pointer ;
    { This is called when an instance of your custom polygon type is being destroyed.
      This is your chance for polygon instance specific memory deallocation.
      'data' is a pointer to the memory allocated via the 'alloc' callback. }
    Free       : procedure
                 (        Instance    : Pointer                ) ;
    { This is called before the mesh is being updated }
    Update     : function
                 (        Instance    : Pointer                ;
                          LayerNumb   ,
                          ChangeFlags : Integer                ;
                          PolTypeInfo : PLWPolygonTypeAccess   ) : Integer ;

  end;

  PLWPolygonHandler = ^TLWPolygonHandler ;
  TLWPolygonHandler = record
    Inst  : PLWInstanceFuncs ;
    Item  : PLWItemFuncs     ;
  end;

implementation

end.

